package lg.minecraft.plugin.testeconomy.storage.model;

import lg.minecraft.plugin.testeconomy.TestEconomy;
import lg.minecraft.plugin.testeconomy.storage.FileStorage;
import lg.minecraft.plugin.testeconomy.storage.StorageType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

/**
 * @author langle__
 * @version 1.0
 */
public class XMLStorage extends FileStorage {

    private static final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();

    private final File file;

    private Document document;

    public XMLStorage() {
        this.file = new File(TestEconomy.getManiConfig().getXmlPath());
    }

    @Override
    public StorageType getType() {
        return StorageType.XML;
    }

    @Override
    protected Double getMoney(String playerName) {
        Element root = this.document.getDocumentElement();
        NodeList list = root.getChildNodes();

        for (int i = 0; i < list.getLength(); i++) {
            Node message = list.item(i);
            if (message.getNodeName().equals(playerName)) {
                try {
                    return Double.parseDouble(message.getTextContent());
                } catch (Exception e) {
                    return null;
                }
            }
        }

        return null;
    }

    @Override
    protected void setMoney(String playerName, double amount) {
        Element root = this.document.getDocumentElement();
        NodeList list = root.getChildNodes();

        boolean playerExists = false;
        for (int i = 0; i < list.getLength(); i++) {
            Node element = list.item(i);
            if (element.getNodeName().equals(playerName)) {
                element.setTextContent(Double.toString(amount));
                playerExists = true;
                break;
            }
        }

        if (!playerExists) {
            // 创建新的玩家节点
            Element newPlayer = this.document.createElement(playerName);
            newPlayer.setTextContent(Double.toString(amount));
            // 将新玩家节点添加到根元素下
            root.appendChild(newPlayer);
        }

        asyncSave();
    }

    @Override
    protected List<String> getPlayers() {
        Element root = this.document.getDocumentElement();
        NodeList list = root.getChildNodes();
        List<String> players = new ArrayList<>();
        for (int i = 0; i < list.getLength(); i++) {
            Element element = (Element) list.item(i);
            players.add(element.getNodeName());
        }
        return players;
    }

    @Override
    public void save() {
        try {
            Transformer transformer = createTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(file);
            transformer.transform(source, result);
        } catch (TransformerException e) {
            TestEconomy.getInstance().getLogger().warning("保存 XML 文件失败: " + file.getName() + ", 错误: " + e.getMessage());
        }
    }

    private Transformer createTransformer() throws TransformerException {
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        return transformer;
    }

    @Override
    public void load() {
        try {
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
            document = file.exists() ? parseExistingFile(builder) : createNewDocument(builder);
        } catch (ParserConfigurationException e) {
            TestEconomy.getInstance().getLogger().severe("无法创建 DocumentBuilder: " + e.getMessage());
        }
    }

    private Document parseExistingFile(DocumentBuilder builder) {
        try {
            return builder.parse(Files.newInputStream(file.toPath()));
        } catch (Exception e) {
            TestEconomy.getInstance().getLogger().warning("解析 XML 文件失败: " + file.getName() + ", 错误: " + e.getMessage());
            return builder.newDocument();
        }
    }

    private Document createNewDocument(DocumentBuilder builder) {
        Document document = builder.newDocument();
        Element root = document.createElement("root");
        document.appendChild(root);
        return document;
    }

}
